iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 15
0
Modern Web

寫JS30天系列 第 15

JS 30 - 15 - Local Storage

  • 分享至 

  • xImage
  •  

讓一個todolist能在關閉瀏覽器後,仍然能保有資料

html

<div class="wrapper">
    <h2>LOCAL TAPAS</h2>
    <p></p>
    <ul class="plates">
        <li>Loading Tapas...</li>
    </ul>
    <form class="add-items">
        <input type="text" name="item" placeholder="Item Name" required>
        <input type="submit" value="+ Add Item">
    </form>
</div>

我們要完成

  1. 將資料存在一個陣列
  2. 當網頁載入時,將儲存的資料顯示在畫面上
  3. +Add Item按鈕被按下,新增一筆資料,並存起來
  4. checkbox被按下,改變狀態並存起來

首先我們宣告一個items陣列為空陣列,拿來儲存未來新增的task(物件形式)
並將陣列內即將增加的task渲染到html上
並未每個li element依照index編號

const items = []; //用來存放task,之後也會將這個陣列存在瀏覽器的localStorage
const itemsList = document.querySelector('.plates');  //要顯示task的地方

//讓存放陣列的items去跑map()方法,跑出一串html
function populateList(plates = [], platesList) {
    platesList.innerHTML = plates.map((plate, index) => {
        return `
            <li>
                <input type="checkbox" data-index='${index}' id="item${index}" ${plate.done ? 'checked' : ''}>
                <label for="item${index}">${plate.text}</label>
            </li>
        `;
    }).join('');
}

populateList(items, itemsList);  //在網頁開啟時就會將存放在localStorage的items跑一次(渲染在html)

首先先將todolist完成(需求第三點)
當我們按下+Add Item按鈕
就會將task新增到.plate

const addItems = document.querySelector('.add-items');  //新增task區的formtag
const itemsList = document.querySelector('.plates');  //顯示task區

addItems.addEventListener('submit', addItem);  //監聽`.addItem`中有submit情況發生

當submit被按下會發現整個網頁都被更新了
這是瀏覽器的預設行為: Varies (send the content of the form to the server).
傳送內容至伺服器
因此我們要取消這個行為
使用e.preventDefault()阻止預設行為
這樣網頁就不會重新整理了

接著我們要取得使用者輸入的內容(需求第一點)
因此我們用變數text存起來
接著將每筆資料存成一個物件
需要紀錄的東西有以下兩個

  1. 輸入的內容
  2. 完成的狀態

這邊item底下的text key/value pairs之所以可以只寫text,
是因為keyname剛好與value相同
最後將資料傳到我們要的items

function addItem(e) {
    e.preventDefault();
    const text = (this.querySelector('[name=item]')).value;
    const item = {
        text,  //text: text,
        done: false
    }
    items.push(item);
    populateList(items, itemsList); //將資料傳入,自動生成html架構
    this.reset();  //清除value內容
}

接下來我們要處理「將資料存起來」
瀏覽器有提供一個讓我們暫存小資料的地方
叫做localStorage或者sessionStorage
兩者差異在sessionStorage會在關閉瀏覽器後,資料就遺失
localStorage則是永久存在瀏覽器內
除非自己去刪除他
另外,由於localStorage只能用setItem()存string
不然會得到兩個[object]、[object]
所以使用JSON.stringify()來轉成字串

function addItem(e) {
    .
    .
    .
    localStorage.setItem('items', JSON.stringify(items));
    this.reset();  //清除value內容
}

既然有儲存,就會有讀取
沒次在重啟網頁的時候我們要將儲存的字串轉回js看得懂的東西(這裡是陣列)
如果沒有東西則是空陣列
然後再渲染到網頁上

const items = JSON.parse(localStorage.getItem('items')) || [];

populateList(items, itemsList);

最後我們要做完成checkbox的存取


function toggleDone(e) {
    console.log(e.target)
}
itemsList.addEventListener('click', toggleDone);

會得到兩個elements
如下

<label for="item4">loojdkjf</label>
<input type="checkbox" data-index="0" id="item0">

但是我們只需要input那個
所以寫一個if判別式
如果沒有input判別式的就直接終止function
剩下的則是依照index去得知是哪個元素被點擊
改變他done的所存的boolean
最後一樣紀錄下來


function toggleDone(e) {
    if (!e.target.matches('input')) return;
    let el = e.target;
    let index = el.dataset.index;
    items[index].done = !items[index].done;
    localStorage.setItem('items', JSON.stringify(items));
}
itemsList.addEventListener('click', toggleDone);

Demo
完整程式碼


上一篇
JS 30 - 14 - Reference Copy or Value Copy
下一篇
JS 30 - 16 - Mouse Move Shadow
系列文
寫JS30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言